﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common.OjbectPool
{
    /// <summary>
    /// A pooling simple interface.
    /// </summary>
    /// <typeparam name="T">Type of element pooled in this pool.</typeparam>
    public interface IObjectPool<T>:IDisposable
    {

        /// <summary>
        /// Obtains an instance from this pool.
        /// Instances returned from this method will have been either newly created
        /// with <see cref="IPooledObjectFactory#MakeObject"/>  or will be a previously
        /// idle object and have been activated with
        /// <see cref="IPooledObjectFactory#ActivateObject"/> and then validated with
        /// <see cref="PooledObjectFactory#ValidateObject"/>.
        /// <p>
        /// By contract, clients <strong>must</strong> return the borrowed instance
        /// using <see cref="ReturnObject"/>, <see cref="InvalidateObject"/> , or a related
        /// method as defined in an implementation or sub-interface.
        /// </p>
        /// The behaviour of this method when the pool has been exhausted
        /// is not strictly specified (although it may be specified by
        /// implementations).
        /// </summary>
        /// <exception cref="Exception"> when <see cref="IPooledObjectFactory#MakeObject"/> throws an  exception.</exception>
        ///<exception cref="NoSuchElementException">
        ///  when the pool is exhausted and cannot or will not return
        ///  another instance.
        /// </exception>
        /// <returns>an instance from this pool.</returns>
        T BorrowObject();
        /// <summary>
        /// description please reference <see cref="BorrowObject"/>
        /// </summary>
        /// <seealso cref="BorrowObject"/>
        /// <param name="maxWaitMillis">get one instance from the pool,max wait time in milliseconds</param>
        /// <returns></returns>
        T BorrowObject(long maxWaitMillis);
        /// <summary>
        /// Return an instance to the pool. By contract, <c>obj</c>
        /// <strong>must</strong> have been obtained using <see cref="BorrowObject"/> or
        /// a related method as defined in an implementation or sub-interface.
        /// </summary>
        /// <param name="obj">a<see cref="BorrowObject"/> borrowed instance to be returned.</param>
        ///<exception cref="Exception">if an instance cannot be returned to the pool</exception>
        void ReturnObject(T obj);


        /// <summary>
        /// Invalidates an object from the pool.
        /// <p>
        /// By contract, <c>obj</c> <strong>must</strong> have been obtained
        /// using <see cref="BorrowObject"/> or a related method as defined in an
        /// implementation or sub-interface.
        /// </p>
        /// This method should be used when an object that has been borrowed is
        /// determined (due to an exception or other problem) to be invalid.
        /// </summary>
        /// <param name="obj">a <see cref="BorrowObject"/> borrowed instance to be disposed.</param>
        /// <exception cref="Exception">if the instance cannot be invalidated</exception>
        void InvalidateObject(T obj);

        /// <summary>
        /// Create an object using the <see cref="IPooledObjectFactory"/>  factory or other
        /// implementation dependent mechanism, passivate it, and then place it in
        /// the idle object pool. <c>addObject</c> is useful for "pre-loading"
        /// a pool with idle objects. (Optional operation).
        /// </summary>
        /// <exception cref="Exception">when <see cref="IPooledObjectFactory#MakeObject"/> fails.</exception>
        void AddObject();

        /// <summary>
        /// Return the number of instances currently idle in this pool. This may be
        /// considered an approximation of the number of objects that can be
        ///<see cref="BorrowObject"/> borrowed without creating any new instances.
        /// Returns a negative value if this information is not available.
        /// </summary>
        /// <returns>the number of instances currently idle in this pool.</returns>
        int GetNumIdle();

        /// <summary>
        ///  Return the number of instances currently borrowed from this pool. Returns
        ///  a negative value if this information is not available.
        /// </summary>
        /// <returns>the number of instances currently borrowed from this pool.</returns>

        int GetNumActive();



        /// <summary>
        ///  Clears any objects sitting idle in the pool, releasing any associated
        ///  resources (optional operation). Idle objects cleared must be <see cref="IPooledObjectFactory#DestroyObject(PooledObject)"/>
        /// </summary>
        /// <exception cref="Exception">if the pool cannot be cleared</exception>
        void Clear();

        /// <summary>
        /// Close this pool, and free any resources associated with it.
        /// <p>
        /// Calling <see cref="AddObject"/>  or  <see cref="BorrowObject"/> after invoking this
        /// method on a pool will cause them to throw an {@link IllegalStateException}.
        /// </p>
        /// Implementations should silently fail if not all resources can be freed.
        /// </summary>

        void Close();
    }
}
